use poker_lib::Suit;

use crate::{
    card_weight::CardWeight,
    nil::NilCheck,
    round::Round,
    table::Table,
    turn::{TurnHandPileState, TurnState},
    utils::Utils,
};
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)]
pub enum EmAIRule {
    None,
    ReachBid,
    AvoidBags,
    PlayNil,
    CoverNil,
    AttackNilAndReachBid,
    AttackNilAndAvoidBags,
    AttackBags, // Easy,
}
impl EmAIRule {
    pub fn to_string(&self) -> &str {
        match self {
            EmAIRule::None => "None",
            EmAIRule::ReachBid => "ReachBid",
            EmAIRule::AvoidBags => "AvoidBags",
            EmAIRule::PlayNil => "PlayNil",
            EmAIRule::CoverNil => "CoverNil",
            EmAIRule::AttackNilAndReachBid => "AttackNilAndReachBid",
            EmAIRule::AttackNilAndAvoidBags => "AttackNilAndAvoidBags",
            EmAIRule::AttackBags => "AttackBags",
        }
    }
}

pub trait IRule {
    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    );
    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    );
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    );
    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    );
}
pub struct RuleEasy;
///简单模式的出牌规则
impl IRule for RuleEasy {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if !_turn_state.is_team_overtrick {
            // 没有满足 trick 打大牌
            let winning_card = &turn.winning_card().card;
            if let Some(card) = Utils::get_highest_rank_from_pile(&_hand_pile.playable_pile) {
                if card.get_number() > winning_card.get_number() {
                    CardWeight::add_card_x(card.get_number(), card, _card_weights);
                    return;
                }
            }
        }
        // 否则跟小牌
        for item in &_hand_pile.playable_pile {
            CardWeight::add_card_x(14 - item.get_number(), item, _card_weights);
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if !_turn_state.is_team_overtrick {
            // 没有满足 trick 打大牌
            let winning_card = &turn.winning_card().card;
            if let Some(card) = Utils::get_highest_rank_from_pile(&_hand_pile.playable_pile) {
                if card.get_number() > winning_card.get_number() {
                    CardWeight::add_card_x(card.get_number(), card, _card_weights);
                    return;
                }
            }
        }
        // 否则跟小牌
        for item in &_hand_pile.playable_pile {
            CardWeight::add_card_x(14 - item.get_number(), item, _card_weights);
        }
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if !_turn_state.is_team_overtrick {
            for item in &_hand_pile.playable_pile {
                CardWeight::add_card_x(item.get_number(), item, _card_weights);
            }
            return;
        }
        for item in &_hand_pile.playable_pile {
            CardWeight::add_card_x(14 - item.get_number(), item, _card_weights);
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if !_turn_state.is_team_overtrick {
            // 没有满足 bid 的情况下
            if _turn_state.is_leading_pre_player_id
                && _turn_state.partner_player_id == turn.winning_card().seat_id
            {
                // 最后一个位置，并且伙伴大
                for item in &_hand_pile.playable_pile {
                    // 取一个非主的小牌跑掉 0 是黑桃
                    if !item.is_trump_card() {
                        CardWeight::add_card_x(14 - item.get_number(), item, _card_weights);
                    } else {
                        CardWeight::add_card_y(14 - item.get_number(), item, _card_weights);
                    }
                }
                return;
            }
            // 空缺的不是黑桃，尝试用黑桃得分
            if _hand_pile.spades_pile.len() > 0 && !turn.leading_card().card.is_trump_card()
            //0 是黑桃
            {
                // 取最小的黑桃得分
                for item in &_hand_pile.spades_pile {
                    CardWeight::add_card_x(14 - item.get_number(), item, _card_weights);
                }
                return;
            } else {
                // 没有主的话，跟一个其他最小的花色
                for item in &_hand_pile.playable_pile {
                    CardWeight::add_card_x(14 - item.get_number(), item, _card_weights);
                }
                return;
            }
        }
        for item in &_hand_pile.playable_pile {
            CardWeight::add_card_x(item.get_number(), item, _card_weights);
        }
    }
}
pub struct RulePlayNil;
/// bid nil 的出牌规则
impl IRule for RulePlayNil {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        let leading_card = &turn.leading_card();
        // let suit = leading_card.card.suit;
        if winning_card.is_trump_card() {
            let mut is_can_follow_big_suit = false;
            if leading_card.card.is_trump_card() {
                //首张主牌
                if _hand_pile.spades_count == 0 {
                    is_can_follow_big_suit = true;
                }
            } else {
                //其他人主牌杀副花色的情况
                if _hand_pile
                    .void_suits
                    .contains(&leading_card.card.get_suit())
                {
                    is_can_follow_big_suit = true;
                }
            }
            if is_can_follow_big_suit {
                //空花色的情况 可以跟一个大的副花色
                let mut has_follow_big_suit = false;
                for item in _hand_pile.playable_pile.iter() {
                    if item.is_trump_card() {
                        continue;
                    }
                    CardWeight::add_card_x(item.get_number(), item, _card_weights);
                    has_follow_big_suit = true;
                }
                if has_follow_big_suit {
                    return;
                }
            }
        }
        if let Some(card) =
            Utils::get_highest_but_less_than_win_card(winning_card, &_hand_pile.playable_pile)
        {
            //打一个比当前赢牌小的但是手牌中最大的
            CardWeight::add_card_x(card.get_number(), &card, _card_weights);
        } else {
            //优先出小的牌 并且花色多的
            Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        self.give_points_as_following_suit_by_player(
            _seat_id,
            _table,
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        );
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        for item in _hand_pile.playable_pile.iter() {
            let card_x = if _hand_pile.lowest_cards.contains(item) {
                item.get_number() as i16
            } else {
                2 as i16
            };
            CardWeight::add_card_x(card_x, item, _card_weights);
            let card_y = (14 - item.get_number()) as i16;

            CardWeight::add_card_y(card_y, item, _card_weights);
            let suit = item.get_suit();
            let card_z = if _hand_pile.void_suits.contains(&suit) {
                1
            } else {
                0
            };
            CardWeight::add_card_z(card_z, item, _card_weights);
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        let leading_card = &turn.leading_card().card;
        // let suit = turn.leading_card().card.suit;
        if winning_card.is_trump_card()
            && !leading_card.is_trump_card()
            && _hand_pile.spades_pile.len() > 0
        {
            if let Some(card) =
                Utils::get_highest_but_less_than_win_card(winning_card, &_hand_pile.spades_pile)
            {
                CardWeight::add_card_x(card.get_number(), &card, _card_weights);
                return;
            }
        }
        for item in _hand_pile.playable_pile.iter() {
            let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
            let history_suit_piles = &_turn_state
                .history_suit_piles
                .get_suit_pocker_cards(item.suit);
            if !item.is_trump_card()
                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
            {
                //跟一张比较大的其他花色的牌 比如红桃6 草花7 查历史牌桌出过的红桃比6大的数量 和出过的草花比7大的数量 这种情况应该是出草花7
                //第一个权重 先计算rank比较大的 而且比rank大的牌处于隐藏状态
                let card_x = 13
                    - Utils::get_greeter_rank_but_hidden_card_nums(item, pile, history_suit_piles)
                        as i8;
                CardWeight::add_card_x(card_x as i16, item, _card_weights);
                //第二个权重是 优先出手里多的花色 todo 这个好像也可以是先出少的花色 可以提高空缺概率
                let card_y = 13 - pile.len() as i16;
                CardWeight::add_card_y(card_y, item, _card_weights);
                //第三个权重取rank
                let card_z = item.get_number() as i16;
                CardWeight::add_card_z(card_z, item, _card_weights);
            }
        }
    }
}

pub struct RuleCoverNil;

impl IRule for RuleCoverNil {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        let leading_card = &turn.leading_card().card;
        let suit = turn.leading_card().card.suit;
        if _turn_state.is_leading_partner {
            self.give_points_as_last_to_play_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
            return;
        }

        let partner_player = _round.get_player_by_id(_turn_state.partner_player_id);
        if partner_player.is_suit_voided(suit) {
            //队友缺这个花色 那就优先获取分数
            if _turn_state.team_bt_delta > 0 {
                if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                    winning_card,
                    &_hand_pile.playable_pile,
                ) {
                    CardWeight::add_card_x(card.get_number(), &card, _card_weights);
                    return;
                }
            }
            Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
            return;
        }
        if Utils::is_card_biggest_now(
            &turn.leading_card().card,
            &turn.play_cards_of_suit().get_suit_pocker_cards(suit),
            &_turn_state.history_suit_piles.get_suit_pocker_cards(suit),
        ) {
            Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
            return;
        }
        //fix: 无法保证收益的情况可以先出一个次小的 同时判定下队友不是空花色 队友牌值的最大情况预估
        if let Some(highest) = Utils::get_highest_rank_from_pile(&_hand_pile.playable_pile) {
            //不能保证赢牌的情况  或者 队友空花色了 跟一个小牌
            let partner_player = _round.get_player_by_id(_turn_state.partner_player_id);
            if highest.get_number() < winning_card.get_number()
                || partner_player.voided_suits.contains(&leading_card.suit)
            {
                Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
                return;
            }
        }

        for item in &_hand_pile.playable_pile {
            let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(suit);
            if _hand_pile.big_cards.contains(item) {
                CardWeight::add_card_x(item.get_number(), item, _card_weights);
            }
            CardWeight::add_card_y(item.get_number(), item, _card_weights);
            CardWeight::add_card_z(13 - pile.len() as i16, item, _card_weights);
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        if let Some(card) =
            Utils::get_lowest_but_greater_than_win_card(winning_card, &_hand_pile.playable_pile)
        {
            if _turn_state.partner_player_id == turn.winning_card().seat_id {
                CardWeight::add_card_x(card.get_number(), &card, _card_weights);
            } else if _turn_state.team_bt_delta > 0 {
                CardWeight::add_card_x(card.get_number(), &card, _card_weights);
            } else {
                Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
            }
        } else {
            Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
        }
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if !_hand_pile.big_cards.is_empty() {
            let mut flag = false;
            for suit in 0..=3 {
                let pile = Utils::get_cards_by_suit(&_hand_pile.big_cards, suit);
                if pile.is_empty() {
                    continue;
                }
                //比Q小的牌
                if let Some(lowest_card) = Utils::get_lowest_rank_card(&pile) {
                    if lowest_card.get_number() < 12 {
                        continue;
                    }
                }
                for item in &pile {
                    let pile2 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
                    let card_x = 13 - pile2.len() as i16;
                    CardWeight::add_card_x(card_x, item, _card_weights);
                    let card_y = item.get_number() as i16;
                    CardWeight::add_card_y(card_y, item, _card_weights);
                }
                flag = true;
            }
            if flag {
                return;
            }
        }

        let partner_player = _round.get_player_by_id(_turn_state.partner_player_id);
        let mut flag2 = false;
        if !partner_player.voided_suits.is_empty() {
            for item2 in &_hand_pile.playable_pile {
                if partner_player.is_suit_voided(item2.suit) {
                    flag2 = true;
                    break;
                }
            }
        }
        if flag2 {
            for item3 in &_hand_pile.playable_pile {
                if !item3.is_trump_card()
                    || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                    || _hand_pile.spades_pile.len() > 2
                {
                    let card_y = if partner_player.is_suit_voided(item3.suit) {
                        99
                    } else {
                        0
                    };
                    CardWeight::add_card_y(card_y, item3, _card_weights);
                    let card_z = if !_hand_pile.big_cards.contains(item3) {
                        item3.get_number() as i16
                    } else {
                        110 + item3.get_number() as i16
                    };
                    CardWeight::add_card_z(card_z, item3, _card_weights);
                }
            }
            return;
        }

        if !_hand_pile.big_cards.is_empty() {
            for item4 in &_hand_pile.playable_pile {
                let pile3 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item4.suit);
                let card_x2 = if _hand_pile.big_cards.contains(item4) {
                    98
                } else {
                    0
                };
                CardWeight::add_card_x(card_x2, item4, _card_weights);
                let card_y2 = pile3.len() as i16;
                CardWeight::add_card_y(card_y2, item4, _card_weights);
                let card_z2 = item4.get_number() as i16;
                CardWeight::add_card_z(card_z2, item4, _card_weights);
            }
            return;
        }

        for item5 in &_hand_pile.playable_pile {
            let pile4 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item5.suit);
            let pile5 = &_turn_state
                .history_suit_piles
                .get_suit_pocker_cards(item5.suit);
            if pile5.len() >= 7
                && !Utils::check_pile_has_rank(pile5, 1)
                && !Utils::check_pile_has_rank(pile4, 1)
            {
                CardWeight::add_card_x(-90, item5, _card_weights);
            }
            let card_x3 = item5.get_number() as i16;
            CardWeight::add_card_x(card_x3, item5, _card_weights);
            let card_y3 = pile4.len() as i16;
            CardWeight::add_card_y(card_y3, item5, _card_weights);
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if _turn_state.partner_player_id == turn.winning_card().seat_id
            && _hand_pile.spades_pile.len() > 0
        {
            CardWeight::add_playable_spades_card_weight(_hand_pile, _card_weights);
            return;
        }
        let suit = turn.leading_card().card.suit;
        let partner_player = _round.get_player_by_id(_turn_state.partner_player_id);
        if _turn_state.is_leading_next_player_id {
            if !partner_player.is_suit_voided(suit) {
                if Utils::is_card_biggest_now(
                    &turn.leading_card().card,
                    &turn.play_cards_of_suit().get_suit_pocker_cards(suit),
                    &_turn_state.history_suit_piles.get_suit_pocker_cards(suit),
                ) {
                    Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
                } else {
                    CardWeight::add_playable_spades_card_weight(_hand_pile, _card_weights);
                }
            } else if _hand_pile.spades_pile.len() >= 3 && !partner_player.has_no_trump_card() {
                if let Some(card) = Utils::get_highest_rank_from_pile(&_hand_pile.spades_pile) {
                    CardWeight::add_card_x(card.get_number() as i16, card, _card_weights);
                }
            } else {
                Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
            }
            return;
        }

        let winning_card = &turn.winning_card().card;
        if _turn_state.team_bt_delta > 0 && _hand_pile.spades_pile.len() >= 2 {
            if !winning_card.is_trump_card() {
                CardWeight::add_playable_spades_card_weight(_hand_pile, _card_weights);
                return;
            }
            if let Some(card) =
                Utils::get_lowest_but_greater_than_win_card(winning_card, &_hand_pile.spades_pile)
            {
                CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                return;
            }
        }
        Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
    }
}

pub struct RuleAvoidBags;

impl IRule for RuleAvoidBags {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        //如果胜出的是伙伴 判定下是跟个大的还是跟个小的
        let turn = _round.cur_turn();
        let win_turn_card = turn.winning_card();
        let winning_card = &win_turn_card.card;
        if _turn_state.partner_player_id == win_turn_card.seat_id {
            //如果当前的trick没有满足 先打小的 留大的
            if !_turn_state.is_other_overtirck {
                Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
                return;
            }
        }
        if winning_card.is_trump_card() && !turn.leading_card().card.is_trump_card() {
            for item in &_hand_pile.playable_pile {
                CardWeight::add_card_x(item.get_number() as i16, item, _card_weights);
            }
            return;
        }
        if let Some(card) =
            Utils::get_highest_but_less_than_win_card(winning_card, &_hand_pile.playable_pile)
        {
            CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
        } else {
            Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        if _turn_state.is_team_overtrick
            && _turn_state.partner_player_id == turn.winning_card().seat_id
        {
            let pile = Utils::get_greater_card_pile(winning_card, &_hand_pile.playable_pile);
            if pile.len() > 0 {
                for item in &pile {
                    CardWeight::add_card_x(item.get_number() as i16, item, _card_weights);
                }
                return;
            }
        }
        self.give_points_as_following_suit_by_player(
            _seat_id,
            _table,
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        );
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        for item in &_hand_pile.playable_pile {
            if !item.is_trump_card()
                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
            {
                let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
                let history_suit_piles = &_turn_state
                    .history_suit_piles
                    .get_suit_pocker_cards(item.suit);
                let card_x =
                    Utils::get_greeter_rank_but_hidden_card_nums(item, pile, history_suit_piles);
                CardWeight::add_card_x(card_x as i16, item, _card_weights);
                let card_y = 13 - pile.len() as i16;
                CardWeight::add_card_y(card_y, item, _card_weights);
            }
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if _hand_pile.playable_pile.len() != _hand_pile.spades_pile.len() {
            for item in &_hand_pile.playable_pile {
                let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
                if !item.is_trump_card() {
                    if _hand_pile.big_cards.contains(item) {
                        CardWeight::add_card_x(item.get_number(), item, _card_weights);
                    }
                    CardWeight::add_card_y(13 - pile.len() as i16, item, _card_weights);
                    CardWeight::add_card_z(item.get_number(), item, _card_weights);
                }
            }
            return;
        }
        let winning_card = &turn.winning_card().card;
        if winning_card.is_trump_card() {
            if _turn_state.is_leading_pre_player_id
                && _turn_state.is_team_overtrick
                && _turn_state.partner_player_id == turn.winning_card().seat_id
            {
                let pile2 = Utils::get_greater_card_pile(winning_card, &_hand_pile.playable_pile);
                if pile2.len() > 0 {
                    for item2 in &pile2 {
                        CardWeight::add_card_x(item2.get_number() as i16, item2, _card_weights);
                    }
                    return;
                }
            }
            if let Some(card) =
                Utils::get_highest_but_less_than_win_card(winning_card, &_hand_pile.playable_pile)
            {
                CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                return;
            }
        }
        for item3 in &_hand_pile.playable_pile {
            CardWeight::add_card_x(item3.get_number() as i16, item3, _card_weights);
        }
    }
}
pub struct RuleAttackNilAndReachBid;

impl IRule for RuleAttackNilAndReachBid {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if !NilCheck::need_attack_nil_as_following(_round, _hand_pile, _turn_state, _card_weights) {
            RuleReachBid.give_points_as_following_suit_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
            if let Some(opponent_player_id) =
                NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
            {
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if !opponent_player.is_suit_voided(turn.leading_card().card.suit) {
                    if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if !NilCheck::need_attack_nil_as_last(_round, _hand_pile, _turn_state, _card_weights) {
            RuleReachBid.give_points_as_last_to_play_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
            if let Some(opponent_player_id) =
                NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
            {
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if !opponent_player.is_suit_voided(turn.leading_card().card.suit) {
                    if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if !NilCheck::need_attack_nil_as_leader(_round, _hand_pile, _turn_state, _card_weights) {
            RuleReachBid.give_points_as_leader_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if NilCheck::need_attack_nil_when_voided_suit(
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        ) {
            return;
        }
        RuleReachBid.give_points_to_voided_suit_by_player(
            _seat_id,
            _table,
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        );
        if let Some(opponent_player_id) = NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
        {
            let opponent_player = _round.get_player_by_id(opponent_player_id);
            for suit_u8 in 0..=4u8 {
                let suit = Suit::from_u8(suit_u8).unwrap();
                if suit != Suit::Spade
                    && suit != Suit::Joker
                    && !opponent_player.is_suit_voided(suit)
                {
                    let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(suit);
                    if pile.is_empty() {
                        continue;
                    }
                    if let Some(card) = Utils::get_lowest_rank_card(pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }
}
pub struct RuleAttackNilAndAvoidBags;

impl IRule for RuleAttackNilAndAvoidBags {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if !NilCheck::need_attack_nil_as_following(_round, _hand_pile, _turn_state, _card_weights) {
            RuleAvoidBags.give_points_as_following_suit_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
            if let Some(opponent_player_id) =
                NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
            {
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if !opponent_player.is_suit_voided(turn.leading_card().card.suit) {
                    if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if !NilCheck::need_attack_nil_as_last(_round, _hand_pile, _turn_state, _card_weights) {
            RuleAvoidBags.give_points_as_last_to_play_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
            if let Some(opponent_player_id) =
                NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
            {
                let turn = _round.cur_turn();
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if !opponent_player.is_suit_voided(turn.leading_card().card.suit) {
                    if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if !NilCheck::need_attack_nil_as_leader(_round, _hand_pile, _turn_state, _card_weights) {
            RuleAvoidBags.give_points_as_leader_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if NilCheck::need_attack_nil_when_voided_suit(
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        ) {
            return;
        }
        RuleAvoidBags.give_points_to_voided_suit_by_player(
            _seat_id,
            _table,
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        );
        if let Some(opponent_player_id) = NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
        {
            for suit_u8 in 0..=3 {
                let suit = Suit::from_u8(suit_u8).unwrap();
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if suit != Suit::Spade
                    && suit != Suit::Joker
                    && !opponent_player.is_suit_voided(suit)
                {
                    let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(suit);
                    if pile.is_empty() {
                        continue;
                    }
                    if let Some(card) = Utils::get_lowest_rank_card(pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }
}
pub struct RuleReachBid;

impl IRule for RuleReachBid {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let leading_card = &turn.leading_card().card;
        let winning_card = &turn.winning_card().card;
        let win_suit = winning_card.suit;
        //3号位
        if _turn_state.is_leading_partner {
            if !leading_card.is_trump_card() {
                let next_player = _round.get_player_by_id(_turn_state.next_player_id);
                if !next_player.is_suit_voided(leading_card.suit) {
                    if let Some(partner_card) =
                        turn.get_play_card_by_seat(_turn_state.partner_player_id)
                    {
                        let history_suit_piles = &_turn_state
                            .history_suit_piles
                            .get_suit_pocker_cards(win_suit);
                        let play_cards_of_suit =
                            &turn.play_cards_of_suit().get_suit_pocker_cards(win_suit);
                        let hand_cards_same_with_win_suit =
                            &_hand_pile.pile_suit_group.get_suit_pocker_cards(win_suit);
                        if Utils::is_partner_win_now_turn(
                            &partner_card,
                            hand_cards_same_with_win_suit,
                            play_cards_of_suit,
                            history_suit_piles,
                        ) {
                            //跟小牌
                            if let Some(card) =
                                Utils::get_lowest_rank_card(&_hand_pile.playable_pile)
                            {
                                CardWeight::add_lowest_card_item(card, _card_weights);
                                return;
                            }
                        }

                        if !winning_card.is_trump_card() {
                            //找一个比对方大的 否则出小牌
                            if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                                winning_card,
                                &_hand_pile.playable_pile,
                            ) {
                                CardWeight::add_card_x(card.get_number(), &card, _card_weights);
                                return;
                            } else {
                                //跟小牌
                                if let Some(card) =
                                    Utils::get_lowest_rank_card(&_hand_pile.playable_pile)
                                {
                                    CardWeight::add_lowest_card_item(card, _card_weights);
                                    return;
                                }
                            }
                        } else {
                            //跟小牌
                            if let Some(card) =
                                Utils::get_lowest_rank_card(&_hand_pile.playable_pile)
                            {
                                CardWeight::add_lowest_card_item(card, _card_weights);
                                return;
                            }
                        }
                    }
                } else {
                    if _turn_state.partner_player_id == turn.winning_card().seat_id {
                        //跟小牌
                        if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                            CardWeight::add_lowest_card_item(card, _card_weights);
                            return;
                        }
                    } else {
                        //找一个比赢家大的 找不到跟小牌
                        if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                            winning_card,
                            &_hand_pile.playable_pile,
                        ) {
                            CardWeight::add_card_x(card.get_number(), &card, _card_weights);
                            return;
                        } else {
                            //跟小牌
                            if let Some(card) =
                                Utils::get_lowest_rank_card(&_hand_pile.playable_pile)
                            {
                                CardWeight::add_lowest_card_item(card, _card_weights);
                                return;
                            }
                        }
                    }
                }
            }
            if _turn_state.partner_player_id == turn.winning_card().seat_id {
                if let Some(partner_card) =
                    turn.get_play_card_by_seat(_turn_state.partner_player_id)
                {
                    let history_suit_piles = &_turn_state
                        .history_suit_piles
                        .get_suit_pocker_cards(win_suit);
                    let win_suit_cards = &turn.play_cards_of_suit().get_suit_pocker_cards(win_suit);

                    if Utils::is_partner_win_now_turn(
                        &partner_card,
                        &_hand_pile.pile_suit_group.get_suit_pocker_cards(win_suit),
                        win_suit_cards,
                        history_suit_piles,
                    ) {
                        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
                        return;
                    }
                }
            }
            CardWeight::add_playable_big_card_weight(_hand_pile, _card_weights);
            return;
        }
        //2号位
        if leading_card.is_trump_card() {
            if _hand_pile.spades_count == 0 {
                //没有黑桃
                if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                    //跟张小牌
                    CardWeight::add_lowest_card_item(card, _card_weights);
                    return;
                }
            } else {
                if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                    winning_card,
                    &_hand_pile.playable_pile,
                ) {
                    //找张大的杀牌
                    CardWeight::add_card_x(card.get_number(), &card, _card_weights);
                    return;
                } else {
                    //找不到大的就跟小的
                    if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                        return;
                    }
                }
            }
        } else {
            if _hand_pile.void_suits.contains(&leading_card.get_suit()) {
                //空缺花色 优先用黑桃杀牌
                if _hand_pile.spades_count > 0 {
                    // 取最小的黑桃得分
                    for item in &_hand_pile.spades_pile {
                        CardWeight::add_card_x(14 - item.get_number(), item, _card_weights);
                    }
                    return;
                } else {
                    // 没有主的话，跟一个其他最小的花色
                    for item in &_hand_pile.playable_pile {
                        CardWeight::add_card_x(14 - item.get_number(), item, _card_weights);
                    }
                    return;
                }
            } else {
                let player2 = _round.get_player_by_id(_turn_state.next_player_id);
                if !player2.is_suit_voided(leading_card.suit) && !_hand_pile.big_cards.is_empty() {
                    CardWeight::add_playable_big_card_weight(_hand_pile, _card_weights);
                } else {
                    Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
                }
            }
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn: &crate::turn::TurnPlay = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        let leading_card = &turn.leading_card().card;
        if leading_card.is_trump_card() || !winning_card.is_trump_card() {
            if _turn_state.partner_player_id != turn.winning_card().seat_id {
                if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                    winning_card,
                    &_hand_pile.playable_pile,
                ) {
                    CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                    return;
                }
            } else {
                Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
                return;
            }
        }
        if _turn_state.partner_player_id == turn.winning_card().seat_id {
            Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
            return;
        }
        //优先保留大牌
        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
        // if !leading_card.is_trump_card() {
        //     CardWeight::add_playable_mid_card_weight(_hand_pile, _card_weights);
        // } else {
        //     compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
        // }
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if _hand_pile.spades_pile.len() >= 6 {
            for item in &_hand_pile.spades_pile {
                if _hand_pile.big_cards.contains(item) {
                    CardWeight::add_card_x(item.get_number(), item, _card_weights);
                }
                CardWeight::add_card_y((14 - item.get_number()) as i16, item, _card_weights);
            }
            return;
        }
        let player = _round.get_player_by_id(_turn_state.partner_player_id);
        let player2 = _round.get_player_by_id(_turn_state.pre_player_id);
        let player3 = _round.get_player_by_id(_turn_state.next_player_id);
        if Utils::check_pile_has_rank(&_hand_pile.playable_pile, 1) {
            let mut flag = false;
            for item2 in &_hand_pile.playable_pile {
                let suit = item2.suit;
                if !item2.is_trump_card()
                    || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                {
                    let pile = &_turn_state.history_suit_piles.get_suit_pocker_cards(suit);
                    if item2.get_number() == 14 && pile.is_empty() {
                        let pile2 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(suit);
                        let card_x = item2.get_number() as i16;
                        CardWeight::add_card_x(card_x, item2, _card_weights);
                        let card_y = 13 - pile2.len() as i16;
                        CardWeight::add_card_y(card_y, item2, _card_weights);
                        flag = true;
                    }
                }
            }
            if flag {
                return;
            }
        }
        if player.voided_suits.len() > 0
            && Utils::has_suit_poker_in_other_voided_suit_list(
                &_hand_pile.playable_pile,
                &player.voided_suits,
            )
        {
            if Utils::has_suit_poker_in_other_voided_suit_list(
                &_hand_pile.big_cards,
                &player.voided_suits,
            ) {
                for item3 in &_hand_pile.big_cards {
                    if !item3.is_trump_card()
                        || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                    {
                        let item3_suit = item3.suit;
                        let pile3 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item3_suit);
                        let card_x = if player.is_suit_voided(item3_suit) {
                            100
                        } else {
                            0
                        };
                        CardWeight::add_card_x(card_x, item3, _card_weights);
                        let card_y = 13 - pile3.len() as i16;
                        CardWeight::add_card_y(card_y, item3, _card_weights);
                        let card_z = item3.get_number() as i16;
                        CardWeight::add_card_z(card_z, item3, _card_weights);
                    }
                }
                return;
            }
            for item4 in &_hand_pile.playable_pile {
                let item4_suit = item4.suit;
                if !item4.is_trump_card()
                    || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                {
                    let pile4 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item4_suit);
                    if _hand_pile.big_cards.contains(item4) {
                        CardWeight::add_card_x(item4.get_number(), item4, _card_weights);
                    }
                    let mut num2 = if player.is_suit_voided(item4_suit) {
                        13 - pile4.len() as i16
                    } else {
                        0
                    };
                    CardWeight::add_card_y(num2, item4, _card_weights);
                    num2 = (14 - item4.get_number()) as i16;
                    CardWeight::add_card_z(num2, item4, _card_weights);
                }
            }
            return;
        }
        if player2.voided_suits.len() > 0 || player3.voided_suits.len() > 0 {
            let mut list = Vec::new();
            for suit_u8 in 0..=3u8 {
                let suit = Suit::from_u8(suit_u8).unwrap();
                if player2.voided_suits.contains(&suit) || player3.voided_suits.contains(&suit) {
                    list.push(suit);
                }
            }
            if Utils::has_suit_poker_in_other_voided_suit_list(&_hand_pile.playable_pile, &list) {
                if list.len() < 3 {
                    let mut flag2 = false;
                    for item5 in &_hand_pile.big_cards {
                        if !list.contains(&item5.suit) {
                            flag2 = true;
                            break;
                        }
                    }
                    if flag2 {
                        for item6 in &_hand_pile.big_cards {
                            let item6_suit = item6.suit;
                            if !item6.is_trump_card()
                                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                            {
                                let pile5 =
                                    &_hand_pile.pile_suit_group.get_suit_pocker_cards(item6_suit);
                                let card_x3 = if !list.contains(&item6.suit) { 100 } else { 0 };
                                CardWeight::add_card_x(card_x3, item6, _card_weights);
                                let card_x3 = 13 - pile5.len() as i16;
                                CardWeight::add_card_y(card_x3, item6, _card_weights);
                                let card_x3 = item6.get_number() as i16;
                                CardWeight::add_card_z(card_x3, item6, _card_weights);
                            }
                        }
                        return;
                    }
                    if Utils::has_suit_poker_in_other_voided_suit_list(
                        &_hand_pile.playable_pile,
                        &list,
                    ) {
                        for item7 in &_hand_pile.playable_pile {
                            let item_suit = item7.suit;
                            if !item7.is_trump_card()
                                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                            {
                                let pile6 =
                                    &_hand_pile.pile_suit_group.get_suit_pocker_cards(item_suit);
                                let card_x4 = if !list.contains(&item7.suit) { 100 } else { 0 };
                                CardWeight::add_card_x(card_x4, item7, _card_weights);
                                let card_x4 = 13 - pile6.len() as i16;
                                CardWeight::add_card_y(card_x4, item7, _card_weights);
                                let card_x4 = (14 - item7.get_number()) as i16;
                                CardWeight::add_card_z(card_x4, item7, _card_weights);
                            }
                        }
                        return;
                    }
                }
                for item8 in &_hand_pile.playable_pile {
                    let item_suit = item8.suit;
                    if !item8.is_trump_card()
                        || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                    {
                        let pile7 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item_suit);
                        let card_x5 = if list.contains(&item_suit) { 100 } else { 0 };
                        CardWeight::add_card_x(card_x5, item8, _card_weights);
                        let card_x5 = 13 - pile7.len() as i16;
                        CardWeight::add_card_y(card_x5, item8, _card_weights);
                        let card_x5 = (14 - item8.get_number()) as i16;
                        CardWeight::add_card_z(card_x5, item8, _card_weights);
                    }
                }
                return;
            }
        }
        CardWeight::add_playable_card_weight(_hand_pile, _card_weights);
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        let win_suit = winning_card.suit;
        let leading_card = &turn.leading_card().card;
        if _turn_state.is_leading_pre_player_id {
            if !leading_card.is_trump_card()
                && _hand_pile.spades_pile.len() > 0
                && _turn_state.partner_player_id != turn.winning_card().seat_id
            {
                if !winning_card.is_trump_card() {
                    CardWeight::add_playable_spades_card_weight(_hand_pile, _card_weights);
                    return;
                }
                if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                    winning_card,
                    &_hand_pile.spades_pile,
                ) {
                    CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                    return;
                }
            }
            Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
            return;
        }
        if _turn_state.is_leading_partner {
            if !leading_card.is_trump_card() {
                if winning_card.is_trump_card() {
                    //有人杀牌
                    if _turn_state.partner_player_id != turn.winning_card().seat_id {
                        //非队友杀牌 找个最小黑桃杀牌
                        if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                            winning_card,
                            &_hand_pile.spades_pile,
                        ) {
                            CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                            return;
                        }
                    } else {
                        //当前赢牌的是队友 直接跑个小牌
                        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
                        return;
                    }
                } else {
                    let next_player = _round.get_player_by_id(_turn_state.next_player_id);
                    if (!next_player.is_suit_voided(leading_card.suit)
                        || _turn_state.team_bt_delta > 0)
                        && _hand_pile.spades_pile.len() > 0
                    {
                        if let Some(partner_card) =
                            turn.get_play_card_by_seat(_turn_state.partner_player_id)
                        {
                            let history_suit_piles = &_turn_state
                                .history_suit_piles
                                .get_suit_pocker_cards(win_suit);
                            let win_suit_cards =
                                &turn.play_cards_of_suit().get_suit_pocker_cards(win_suit);
                            let hand_cards_same_with_win_suit =
                                &_hand_pile.pile_suit_group.get_suit_pocker_cards(win_suit);

                            if !Utils::is_partner_win_now_turn(
                                &partner_card,
                                hand_cards_same_with_win_suit,
                                win_suit_cards,
                                history_suit_piles,
                            ) {
                                if !winning_card.is_trump_card() {
                                    CardWeight::add_playable_spades_card_weight(
                                        _hand_pile,
                                        _card_weights,
                                    );
                                    return;
                                }
                                if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                                    winning_card,
                                    &_hand_pile.spades_pile,
                                ) {
                                    CardWeight::add_card_x(
                                        card.get_number() as i16,
                                        &card,
                                        _card_weights,
                                    );
                                    return;
                                }
                            }
                        }
                    }
                }
                Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
            } else {
                if let Some(partner_card) =
                    turn.get_play_card_by_seat(_turn_state.partner_player_id)
                {
                    let history_suit_piles = &_turn_state
                        .history_suit_piles
                        .get_suit_pocker_cards(win_suit);
                    let win_suit_cards = &turn.play_cards_of_suit().get_suit_pocker_cards(win_suit);
                    let hand_cards_same_with_win_suit =
                        &_hand_pile.pile_suit_group.get_suit_pocker_cards(win_suit);
                    if Utils::is_partner_win_now_turn(
                        partner_card,
                        hand_cards_same_with_win_suit,
                        win_suit_cards,
                        history_suit_piles,
                    ) {
                        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
                    } else {
                        CardWeight::add_playable_big_card_weight(_hand_pile, _card_weights);
                    }
                }
            }
            return;
        }

        if !leading_card.is_trump_card() && _hand_pile.spades_pile.len() > 0 {
            if _turn_state.team_bt_delta > 0
                || (_turn_state.other_bt_delta > 0
                    && _turn_state.team_total_bags + 1 < _table.limit_bag)
            {
                //优先杀牌得分
                CardWeight::add_playable_spades_card_weight(_hand_pile, _card_weights);
                return;
            }
            // let player2 = _round.get_player_by_id(_turn_state.next_player_id);
            // if !player2.is_suit_voided(leading_card.suit)
            //     || (_turn_state.team_bt_delta <= 0 && _turn_state.other_bt_delta > 0)
            // {
            //     CardWeight::add_playable_spades_card_weight(_hand_pile, _card_weights);
            //     return;
            // }
        }
        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
    }
}
pub struct RuleAttackBag;
impl IRule for RuleAttackBag {
    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
    }

    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        Utils::compute_fewer_card_num_and_lower_rank(_hand_pile, _card_weights);
    }
}
